package com.rbac.controller;

import com.rbac.common.Result;
import com.rbac.common.RedisKey;
import com.rbac.dto.LoginDTO;
import com.rbac.entity.SysPermission;
import com.rbac.entity.SysUser;
import com.rbac.service.RedisService;
import com.rbac.service.UserService;
import com.rbac.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.time.Duration;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import com.rbac.mapper.UserMapper;

@RestController
@RequestMapping("/auth")
@CrossOrigin
public class AuthController {
	
	private static final String CAPTCHA_SESSION_KEY = "captcha";
	
	@Autowired
	private UserService userService;
	
	@Autowired
	private PasswordEncoder passwordEncoder;
	
	@Autowired
	private JwtUtil jwtUtil;

	@Autowired
	private RedisService redisService;
	
	@Autowired
	private UserMapper userMapper;
	
	@PostMapping("/login")
	public Result<Map<String, Object>> login(@Valid @RequestBody LoginDTO loginDTO, HttpSession session, HttpServletRequest request) {
		// 验证验证码 - 改为从Redis读取
		String captchaId = session.getId(); // 默认使用sessionId，前端可传captchaId
		String key = RedisKey.CAPTCHA_CODE.build("dev", captchaId);
		String cachedCaptcha = redisService.getString(RedisKey.CAPTCHA_CODE, captchaId);
		
		if (cachedCaptcha == null) {
			return Result.error("验证码已过期，请重新获取");
		}
		
		if (!cachedCaptcha.equalsIgnoreCase(loginDTO.getCaptcha().trim())) {
			return Result.error("验证码错误");
		}
		
		// 验证后清除Redis中的验证码
		redisService.delete(RedisKey.CAPTCHA_CODE, captchaId);
		
		// 查询用户
		SysUser user = userService.getUserByUsername(loginDTO.getUsername());
		if (user == null) {
			return Result.error("用户名或密码错误");
		}
		
		// 验证密码
		if (!passwordEncoder.matches(loginDTO.getPassword(), user.getPassword())) {
			return Result.error("用户名或密码错误");
		}
		
		// 检查用户状态
		if (user.getStatus() != 1) {
			return Result.error("用户已被禁用");
		}
		
		// 根据记住我选项设置token过期时间
		String token;
		if (loginDTO.getRememberMe() != null && loginDTO.getRememberMe()) {
			// 记住我：30天
			token = jwtUtil.generateToken(user.getUsername(), 30 * 24 * 60 * 60 * 1000L);
		} else {
			// 默认：24小时
			token = jwtUtil.generateToken(user.getUsername());
		}
		
		// 计算Token剩余TTL
		Date exp = jwtUtil.getExpirationDateFromToken(token);
		long seconds = Math.max(1, (exp.getTime() - System.currentTimeMillis()) / 1000);
		Duration tokenTtl = Duration.ofSeconds(seconds);
		
		// 写入在线用户与会话缓存
		redisService.setString(RedisKey.ONLINE_USER, token, tokenTtl, String.valueOf(user.getId()));
		redisService.setString(RedisKey.TOKEN_TO_USER, String.valueOf(user.getId()), tokenTtl, token);
		redisService.setJson(RedisKey.USER_SESSION, user, tokenTtl, String.valueOf(user.getId()));
		
		// 缓存用户权限和菜单
		List<String> permissions = userMapper.selectUserPermissions(user.getUsername());
		if (permissions != null && !permissions.isEmpty()) {
			redisService.setString(RedisKey.USER_PERMISSIONS, String.join(",", permissions), null, user.getUsername());
		}
		
		List<SysPermission> menus = userMapper.selectUserMenus(user.getUsername());
		if (menus != null && !menus.isEmpty()) {
			redisService.setJson(RedisKey.USER_MENUS, menus, null, String.valueOf(user.getId()));
		}
		
		// 返回用户信息和Token
		Map<String, Object> result = new HashMap<>();
		result.put("token", token);
		result.put("user", user);
		result.put("rememberMe", loginDTO.getRememberMe());
		
		return Result.success("登录成功", result);
	}
	
	@PostMapping("/register")
	public Result<String> register(@Valid @RequestBody SysUser user) {
		// 检查用户名是否已存在
		SysUser existUser = userService.getUserByUsername(user.getUsername());
		if (existUser != null) {
			return Result.error("用户名已存在");
		}
		
		// 新增用户
		boolean success = userService.addUser(user);
		if (success) {
			return Result.success("注册成功");
		} else {
			return Result.error("注册失败");
		}
	}
	
	/**
	 * 获取用户权限
	 */
	@GetMapping("/permissions")
	public Result<List<String>> getUserPermissions() {
		List<String> permissions = userService.getUserPermissions();
		return Result.success(permissions);
	}
	
	/**
	 * 调试接口：获取用户详细信息
	 */
	@GetMapping("/debug/user-info")
	public Result<Map<String, Object>> getDebugUserInfo() {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		if (authentication == null || !authentication.isAuthenticated()) {
			return Result.error("用户未登录");
		}
		
		String username = authentication.getName();
		Map<String, Object> debugInfo = new HashMap<>();
		
		// 获取用户基本信息
		SysUser user = userService.getUserByUsername(username);
		debugInfo.put("user", user);
		
		// 获取用户角色ID
		List<Long> roleIds = userService.getRoleIdsByUserId(user.getId());
		debugInfo.put("roleIds", roleIds);
		
		// 获取用户角色名称
		List<String> roleNames = userService.getRoleNamesByUserId(user.getId());
		debugInfo.put("roleNames", roleNames);
		
		// 获取用户权限
		List<String> permissions = userService.getUserPermissions();
		debugInfo.put("permissions", permissions);
		
		return Result.success(debugInfo);
	}
	
	// 获取用户菜单
	@GetMapping("/menus")
	public Result<List<SysPermission>> getUserMenus() {
		List<SysPermission> menus = userService.getUserMenus();
		return Result.success(menus);
	}
	
	// 获取用户信息（包含权限）
	@GetMapping("/info")
	public Result<Map<String, Object>> getUserInfo() {
		Map<String, Object> userInfo = userService.getUserInfo();
		return Result.success(userInfo);
	}
	
	/**
	 * 用户登出
	 */
	@PostMapping("/logout")
	public Result<String> logout(HttpServletRequest request) {
		try {
			// 获取当前认证信息
			Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
			String token = extractTokenFromRequest(request);
			if (token != null) {
				// 计算剩余TTL并加入黑名单
				Date exp = jwtUtil.getExpirationDateFromToken(token);
				long seconds = Math.max(1, (exp.getTime() - System.currentTimeMillis()) / 1000);
				redisService.setString(RedisKey.TOKEN_BLACKLIST, "logout", Duration.ofSeconds(seconds), token);
				// 清理在线与映射
				String userId = redisService.getString(RedisKey.TOKEN_TO_USER, token);
				if (userId != null) {
					redisService.delete(RedisKey.ONLINE_USER, userId);
					redisService.delete(RedisKey.USER_SESSION, userId);
				}
				redisService.delete(RedisKey.TOKEN_TO_USER, token);
			}
			if (authentication != null) {
				String username = authentication.getName();
				userService.logout(username);
				SecurityContextHolder.clearContext();
			}
			return Result.success("登出成功");
		} catch (Exception e) {
			System.err.println("登出过程中发生错误: " + e.getMessage());
			e.printStackTrace();
			return Result.error("登出失败: " + e.getMessage());
		}
	}

	private String extractTokenFromRequest(HttpServletRequest request) {
		String bearerToken = request.getHeader("Authorization");
		if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
			return bearerToken.substring(7);
		}
		return null;
	}
}